package com.sunrise.xdoc.view.details;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedProperty;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

import com.sunrise.xdoc.dao.IBaseDao;
import com.sunrise.xdoc.entity.AbstractIdEntity;
import com.sunrise.xdoc.helper.DaoHelper;
import com.sunrise.xdoc.utils.SunriseClassUtils;

public abstract class AbstractDetailView<T extends AbstractIdEntity> implements Serializable {
	private static final long serialVersionUID = 3898359223418040917L;

	@ManagedProperty(value = "#{daoHelper}")
	private DaoHelper daoHelper;

	private Long entityId;
	private T entity;

	private DetailDataModel detailDataModel;

	protected abstract void initialPresentationView(DetailDataModel detailDataModel);

	@PostConstruct
	private void initDetailView() {
		entity = createNewEntity();
		detailDataModel = new DetailDataModel();
	}

	private T createNewEntity() {
		try {
			return getEntityClass().newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			throw new RuntimeException("There is a problem when init the entity");
		}
	}

	/**
	 * Append missing attributes for entity.
	 * 
	 * @param eagerLoadedProperties
	 *            the name of properties need to load with the entity but they
	 *            are mark as LAZY (cause the lazy load exception).
	 */
	protected T loadEntity() {
		if (entityId == null) {
			return createNewEntity();
		}
		IBaseDao<T> dao = daoHelper.getDao(getEntityClass());
		DetachedCriteria dc = dao.getDetachedCriteria();
		dc.add(Restrictions.eq("id", entityId));
		return dao.findFirstByCriteria(dc);
	}

	@SuppressWarnings("unchecked")
	private Class<T> getEntityClass() {
		return (Class<T>) SunriseClassUtils.getArgumentClass(getClass());
	}

	// ///////// Getter setter/////////////
//	public void getAttributeEntityDelegator()
	
	
	public DetailDataModel getDetailDataModel() {
		return detailDataModel;
	}

	public void setDetailDataModel(DetailDataModel detailDataModel) {
		this.detailDataModel = detailDataModel;
	}

	public T getEntity() {
		return entity;
	}

	public void setEntity(T entity) {
		this.entity = entity;
	}

	public Long getEntityId() {
		return entityId;
	}

	/**
	 * Set entityId also load the entity. 
	 * @param entityId
	 */
	public void setEntityId(Long entityId) {
		if (entityId != null && entityId.equals(this.entity)) {
			return;
		}
		this.entityId = entityId;
		loadEntity();
	}

}
